package controllers;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import play.*;
import play.data.*;
import play.mvc.*;
import views.html.*;
import at.ac.tuwien.big.we14.lab2.api.*;
import at.ac.tuwien.big.we14.lab2.api.impl.PlayQuizFactory;
import play.db.jpa.*;
import play.cache.Cache;
import play.data.validation.Constraints.*;
import play.db.jpa.Transactional;
import static java.lang.System.out;
import models.*;
import play.Logger;
import play.libs.*;
import play.cache.Cache;

import java.util.List;
import java.util.ArrayList;

import play.data.validation.ValidationError;
import play.i18n.Lang;
import play.i18n.Messages;





public class BigQuiz extends Controller {
	
	static Form<Player> registerForm  = Form.form(Player.class);

	@Transactional
	public static class Login {
		@Required(message = "login.required.username")
		public String username;
		@Required(message = "login.required.password")
		public String password;
		public String validate() {
			if (Player.authenticate(username, password) == null) {
				return Messages.get("login.error");
			}
			return null;
		}
	}

	@Security.Authenticated(Secured.class)
	public static Result getIndex() {
		return ok(index.render());
	}

	public static Result getAuthentication() {
		return ok(authentication.render(Form.form(Login.class)));
	}

	@Transactional
	public static Result doAuthentication() {
		Form<Login> loginForm = Form.form(Login.class).bindFromRequest();
		if (loginForm.hasErrors()) {
			return badRequest(authentication.render(loginForm));
		} else {
			session().clear();
			session().put("username", loginForm.get().username);
			return redirect(controllers.routes.BigQuiz.getIndex());
		}
	}

	public static Result getRegister() {
		return ok(registration.render(registerForm));
	}

	@Transactional
	public static Result doRegister() {
		Form<Player> filledForm = registerForm.bindFromRequest();
		if(filledForm.hasErrors()) {
			return badRequest(registration.render(filledForm));
		} 
		Player player = filledForm.get();
		Logger.info("Saving player " + player.username);
		player.save();	
		Logger.info("Player " + Player.findByUsername(player.username).username + " has been saved!");
		return ok(authentication.render(Form.form(Login.class)));
	}
		
	@Security.Authenticated(Secured.class)
	@Transactional
	public static Result doGame() {
		String username=session().get("username");
		Player player = Player.findByUsername(username);
		Logger.info("Player '" + player + "' wants a question");
		QuizGame found = (QuizGame) Cache.get(username);
		Logger.info("Cache is " + found);
		// if game not found create one
		if(found==null) {
			found = (new PlayQuizFactory(getJson(), player )).createQuizGame();
			Logger.info("New Quizgame is " + found);
		}
		DynamicForm dform = Form.form().bindFromRequest();
		if(dform.get("seenover")!=null && found.getCurrentRoundCount()>0) {
			if(found.isGameOver()) found = (new PlayQuizFactory(getJson(), player )).createQuizGame();
		}
		
		//game start
		if(found.getCurrentRoundCount()==0)found.startNewRound();
		
		
		if(dform.get("timeleft")!=null) {
			//answer mode
			//out.println(dform.data());
			List<Choice> choices = new ArrayList<>();
			dform.data().remove("timeleft");
			Set<String> keys=dform.data().keySet();
			for(String k : keys) {
				for(Choice c : found.getCurrentRound().getCurrentQuestion(player).getAllChoices()) {
					if(dform.data().get(k).equals(c.getText())) choices.add(c);
				}
			}			
			found.answerCurrentQuestion(player, choices, Long.parseLong(dform.get("timeleft")));
		}
		
		if(found.isRoundOver() && dform.get("seen")==null) {
				Cache.set(username, found);		
				return ok(roundover.render(found,username));
		}else if(found.isGameOver()) {
			Cache.set(username, found);		
			return ok(quizover.render(found,username));
		}else if(found.isRoundOver()){
			found.startNewRound();
		}
		
		Logger.info("Answ1: " + found.getCurrentRound().getAnswer(0, player));
		Logger.info("Answ2: " + found.getCurrentRound().getAnswer(1, player));
		Logger.info("Answ3: " + found.getCurrentRound().getAnswer(2, player));

		Cache.set(username, found);
		return ok(quiz.render(found,username));
	}
	
	private static String getJson() {
		List<Lang> l = request().acceptLanguages();
		if (l.isEmpty()) return "conf/data.en.json";
		if (l.get(0).code().startsWith("de")) return "conf/data.de.json";
		if (l.get(0).code().startsWith("en")) return "conf/data.en.json";
		return "conf/data.en.json";
	}

	@Security.Authenticated(Secured.class)
	public static Result doLogout() {
		session().clear();
		return redirect(controllers.routes.BigQuiz.getIndex());
	}
}
